# -*- coding: utf-8 -*-
# @Time : 2022/4/2 14:54
# @FileName: SelfSelectionTableView.py
# @Mail: lizhigen1996@aliyun.com


__author__ = 'Zhigen.li'

from PyQt5.QtCore import QItemSelectionModel, pyqtSignal, Qt, QModelIndex
from PyQt5.QtGui import QStandardItemModel, QStandardItem, QBrush, QColor, QFont, QCursor
from PyQt5.QtWidgets import QTableView, QAbstractItemView, QItemDelegate, QMessageBox, QAbstractSlider, QMenu, QAction, QWidget
from Tools.Util import *
from threading import Thread
from UI.Curve.YieldRateDialog import YieldRateDialog
from UI.Curve.MonthDataCurve import *
from UI.Curve.HoldingPie import *
import json
from Config.Config import config, CatchExceptions



# 只读代理
class OnlyReadDelegate(QItemDelegate):
    def __init__(self, parent):
        super(OnlyReadDelegate, self).__init__(parent)

    def createEditor(self, QWidget, QStyleOptionViewItem, QModelIndex):
        return None

class SelfSelectionTableView(QTableView, QAbstractSlider):
    fundTabDataSignal = pyqtSignal(dict, bool)
    selfSelWaringSignal = pyqtSignal()
    fundSateChangedSignal = pyqtSignal()
    showCurveSignal = pyqtSignal()
    curveCloseBtnClicked = pyqtSignal(bool)
    monthDataSignal = pyqtSignal(int, str, str, list, list, list, list, list, list)

    def __init__(self, parent, curveWidget: QWidget, dialogs, isSel=True):
        super(SelfSelectionTableView, self).__init__(parent)
        self.isSel = isSel
        self.curveWidget = curveWidget
        self.dialogs = dialogs
        model = QStandardItemModel(0, 17, self)
        selectionModel = QItemSelectionModel(model, self)
        self.setModel(model)
        self.horizontalHeader().setStretchLastSection(True)
        self.setSelectionModel(selectionModel)

        self.setSelectionBehavior(QAbstractItemView.SelectRows)  # 选择整行
        self.setSelectionMode(QAbstractItemView.SingleSelection)  # 只能选择一行
        self.setContextMenuPolicy(Qt.CustomContextMenu)  # 可弹出右键菜单

        self.msgBox = QMessageBox(self)
        self.msgBox.setIcon(QMessageBox.Icon.Warning)
        self.msgBox.setWindowTitle('当前自选基金过多')
        self.msgBox.addButton(QMessageBox.Yes)
        self.msgBox.button(QMessageBox.Yes).setText('确认')

        model.setHorizontalHeaderItem(0, QStandardItem('基金代码'))
        model.setHorizontalHeaderItem(1, QStandardItem('基金简称'))
        model.setHorizontalHeaderItem(2, QStandardItem('成立日期'))
        model.setHorizontalHeaderItem(3, QStandardItem('今年来'))
        model.setHorizontalHeaderItem(4, QStandardItem('近1周'))
        model.setHorizontalHeaderItem(5, QStandardItem('近1月'))
        model.setHorizontalHeaderItem(6, QStandardItem('近3月'))
        model.setHorizontalHeaderItem(7, QStandardItem('近6月'))
        model.setHorizontalHeaderItem(8, QStandardItem('近1年'))
        model.setHorizontalHeaderItem(9, QStandardItem('近2年'))
        model.setHorizontalHeaderItem(10, QStandardItem('近3年'))
        model.setHorizontalHeaderItem(11, QStandardItem('近5年'))
        model.setHorizontalHeaderItem(12, QStandardItem('成立来'))
        model.setHorizontalHeaderItem(13, QStandardItem('海通证券评级'))
        model.setHorizontalHeaderItem(14, QStandardItem('招商证券评级'))
        model.setHorizontalHeaderItem(15, QStandardItem('上海证券评级'))
        model.setHorizontalHeaderItem(16, QStandardItem('济安金信评级'))

        # 设置只读
        self.setItemDelegate(OnlyReadDelegate(self))

        self.fundTabDataSignal.connect(self.setTabData)
        self.selfSelWaringSignal.connect(self.onSelfSelWaring)

        # 选中穴位改变信号
        self.selectionModel().currentChanged.connect(self.onCurrentRowChanged)
        self.clicked.connect(self.onClicked)
        self.monthDataSignal.connect(self.onMonthData)

        # 添加右击菜单
        self.popMenu = QMenu(self)
        if isSel:
            self.delAction = QAction()
            self.delAction.setText('取消自选')  # 刷新 添加定时
            self.delAction.triggered.connect(self.delSelfSelection)
            self.flashActioon = QAction()
            self.flashActioon.setText('刷新')
            self.flashActioon.triggered.connect(self.showEvent)

            self.navAction = QAction()
            self.navAction.setText('月初净值月末净值对比')
            self.navAction.triggered.connect(self.onMonthDataActionTriggered)
            self.perAction = QAction()
            self.perAction.setText('月最高涨、最低跌收益百分比')
            self.perAction.triggered.connect(self.onMonthDataActionTriggered)
            self.fluAction = QAction()
            self.fluAction.setText('月波动值（最高涨、最低跌之差）')
            self.fluAction.triggered.connect(self.onMonthDataActionTriggered)
            self.difAction = QAction()
            self.difAction.setText('月净值差值(月末减月初，该月是否盈亏）')
            self.difAction.triggered.connect(self.onMonthDataActionTriggered)

            self.holdAction = QAction()
            self.holdAction.setText('持仓占比')
            self.holdAction.triggered.connect(self.onHoldActionTriggered)

            self.detailsAction = QAction()
            self.detailsAction.setText('详细信息')
            self.popMenu.addAction(self.delAction)
            self.popMenu.addAction(self.flashActioon)
            self.popMenu.addAction(self.holdAction)
            self.popMenu.addAction(self.navAction)
            self.popMenu.addAction(self.perAction)
            self.popMenu.addAction(self.fluAction)
            self.popMenu.addAction(self.difAction)
            self.popMenu.addAction(self.detailsAction)
        else:
            self.addAction = QAction()
            self.addAction.setText('添加自选')
            self.addAction.triggered.connect(self.addSelfSelection)
            self.flashActioon = QAction()
            self.flashActioon.setText('刷新')
            self.flashActioon.triggered.connect(self.showEvent)

            self.navAction = QAction()
            self.navAction.setText('月初净值月末净值对比')
            self.navAction.triggered.connect(self.onMonthDataActionTriggered)
            self.perAction = QAction()
            self.perAction.setText('月最高涨、最低跌收益百分比')
            self.perAction.triggered.connect(self.onMonthDataActionTriggered)
            self.fluAction = QAction()
            self.fluAction.setText('月波动值（最高涨、最低跌之差）')
            self.fluAction.triggered.connect(self.onMonthDataActionTriggered)
            self.difAction = QAction()
            self.difAction.setText('月净值差值(月末减月初，该月是否盈亏）')
            self.difAction.triggered.connect(self.onMonthDataActionTriggered)

            self.holdAction = QAction()
            self.holdAction.setText('持仓占比')
            self.holdAction.triggered.connect(self.onHoldActionTriggered)

            # self.detailsAction = QAction()
            # self.detailsAction.setText('详细信息')
            self.popMenu.addAction(self.addAction)
            self.popMenu.addAction(self.flashActioon)
            self.popMenu.addAction(self.holdAction)
            self.popMenu.addAction(self.navAction)
            self.popMenu.addAction(self.perAction)
            self.popMenu.addAction(self.fluAction)
            self.popMenu.addAction(self.difAction)
            # self.popMenu.addAction(self.detailsAction)

        # 右键点击事件
        self.customContextMenuRequested.connect(self.slotContextMenu)

    # 加自选
    @CatchExceptions
    def addSelfSelection(self, b):
        index = self.currentIndex()
        fundCodeIdx = self.model().index(index.row(), 0)
        fundCode = self.model().data(fundCodeIdx)
        name = self.model().data(self.model().index(index.row(), 1))
        funds = config.getFund()
        if len(funds) > config.getMaxFundsCount() or len(funds) == config.getMaxFundsCount():
            QMessageBox.warning(self, '当前自选基金过多', '当前自选基金过多，目前仅支持显示 {} 自选。请删除多余自选！'.format(config.getMaxFundsCount()))
            return
        data = fundAccurate(fundCode)
        if not config.addFund(data):
            QMessageBox.warning(self, '自选列表已存在该基金', '自选列表已存在该基金{}，请勿重复添加！'.format(fundCode))
        else:
            self.fundSateChangedSignal.emit()
            QMessageBox.information(self, '添加自选基金成功', '添加自选基金成功！{} {}'.format(fundCode, name))

    @CatchExceptions
    def onHoldActionTriggered(self, b):
        index = self.currentIndex()
        fundCodeIdx = self.model().index(index.row(), 0)
        fundCode = self.model().data(fundCodeIdx)
        name = self.model().data(self.model().index(index.row(), 1))
        targetNames, urls, targetSecids, rates, correlationNames, correlationUrls = equityHoldings(fundCode)
        holdingPie = HoldingPie()
        holdingPie.create_piechart(name, fundCode, targetNames, targetSecids, rates)

    @CatchExceptions
    def onMonthDataActionTriggered(self, b):
        if self.sender() == self.navAction:
            mode = 1
        elif self.sender() == self.perAction:
            mode = 2
        elif self.sender() == self.fluAction:
            mode = 3
        else:
            mode = 4
        index = self.currentIndex()
        fundCodeIdx = self.model().index(index.row(), 0)
        fundCode = self.model().data(fundCodeIdx)
        name = self.model().data(self.model().index(index.row(), 1))

        t = Thread(target=self.monthDataThread, args=[mode, name, fundCode])
        t.start()

    @CatchExceptions
    def monthDataThread(self, mode, name, code):
        mlist, startlist, endlist, maxlist, minlist, reslist = fundMonthData(code)
        self.monthDataSignal.emit(mode, name, code, mlist, startlist, endlist, maxlist, minlist, reslist)

    def onMonthData(self, mode, name, code, mlist, startlist, endlist, maxlist, minlist, reslist):
        if mode == 1:
            m = MonthDataCurve_NavBar(name, code)
            m.showCurve(mlist, startlist, endlist)
        elif mode == 2:
            m = MonthDataCurve_PerBar(name, code)
            m.showCurve(mlist, maxlist, minlist)
        elif mode == 3:
            m = MonthDataCurve_FluBar(name, code)
            m.showCurve(mlist, maxlist, minlist)
        else:
            m = MonthDataCurve_DifBar(name, code)
            m.showCurve(mlist, reslist)

    def slotContextMenu(self, pos):
        index = self.indexAt(pos)
        if index:
            self.popMenu.exec(QCursor.pos())

    # 取消自选
    @CatchExceptions
    def delSelfSelection(self, b):
        if self.model().rowCount() == 0 or self.model().rowCount() < 0:
            return

        index = self.currentIndex()
        fundCodeIdx = self.model().index(index.row(), 0)
        fundCode = self.model().data(fundCodeIdx)
        name = self.model().data(self.model().index(index.row(), 1))

        config.delFund(fundCode)
        self.model().removeRow(index.row())
        self.fundSateChangedSignal.emit()

    @CatchExceptions
    def onClicked(self, index: QModelIndex):
        if index.row() > config.getMaxFundsCount() or index.row() == config.getMaxFundsCount():
            return

        fundCodeIdx = self.model().index(index.row(), 0)
        fundCode = self.model().data(fundCodeIdx)
        name = self.model().data(self.model().index(index.row(), 1))

        typeCode = ''
        title = ''
        if index.column() == 3:
            typeCode = 'sy'
            title = '{}今年来累计收益率走势'.format(name)
        elif index.column() == 5:
            typeCode = 'm'
            title = '{}近一个月累计收益率走势'.format(name)
        elif index.column() == 6:
            typeCode = 'q'
            title = '{}近三个月累计收益率走势'.format(name)
        elif index.column() == 7:
            typeCode = 'hy'
            title = '{}近六个月累计收益率走势'.format(name)
        elif index.column() == 8:
            typeCode = 'y'
            title = '{}近一年累计收益率走势'.format(name)
        elif index.column() == 9:
            typeCode = 'twy'
            title = '{}近两年累计收益率走势'.format(name)
        elif index.column() == 10:
            typeCode = 'try'
            title = '{}近三年累计收益率走势'.format(name)
        elif index.column() == 11:
            typeCode = 'fiy'
            title = '{}近五年累计收益率走势'.format(name)
        elif index.column() == 12:
            typeCode = 'se'
            title = '{}成立来累计收益率走势'.format(name)

        if typeCode:
            self.showCurveSignal.emit()
            data = fundYieldRate(fundCode, typeCode)
            dialog = YieldRateDialog()
            dialog.curveCloseBtnClicked.connect(self.curveCloseBtnClicked)
            dialog.showPlot(data, title)
            if len(self.dialogs) > 0:
                self.curveWidget.layout().removeWidget(self.dialogs[0])
                del self.dialogs[0]

            self.curveWidget.layout().addWidget(dialog)
            # self.curveWidget.resize(100, 1400)
            self.dialogs.append(dialog)

    def onCurrentRowChanged(self, current: QModelIndex, previous: QModelIndex):
        # 选中的cell发生改变
        pass

    @CatchExceptions
    def setTabData(self, data, isShow):
        model = self.model()
        rowNum = self.model().rowCount()

        jdsy = data['jdsy'][0]
        jdsy = jdsy.replace('\'', '')
        jdsyList = jdsy.split(',')

        jjpj = data['jjpj'][0]
        jjpj = jjpj.replace('\'', '')
        jjpjList = jjpj.split(',')

        if isShow:
            for idx in range(len(jdsyList)):
                if not jdsyList[idx]:
                    jdsyList[idx] = '---'

                model.setItem(rowNum, idx, QStandardItem(jdsyList[idx]))
                model.item(rowNum, idx).setTextAlignment(Qt.AlignCenter)

                if idx == 0 or idx == 1:
                    model.item(rowNum, idx).setForeground(QBrush(QColor(0, 52, 151)))
                    font = model.item(rowNum, idx).font()
                    font.setUnderline(True)  # 字体增加下划线
                    model.item(rowNum, idx).setFont(font)

                if idx in range(3, 13):
                    if '%' in jdsyList[idx]:
                        num = jdsyList[idx]
                        num = num.replace('%', '')
                        num = float(num)
                        if num > 0:
                            model.item(rowNum, idx).setForeground(QBrush(QColor(220, 0, 0)))
                        elif num < 0:
                            model.item(rowNum, idx).setForeground(QBrush(QColor(9, 124, 37)))

                    model.item(rowNum, idx).setFont(QFont('Microsoft YaHei', 9, 75))  # 字体加粗

            model.setItem(rowNum, 13, QStandardItem(jjpjList[1] if jjpjList[1] else '暂无评级'))
            model.item(rowNum, 13).setTextAlignment(Qt.AlignCenter)
            model.setItem(rowNum, 14, QStandardItem(jjpjList[2] if jjpjList[2] else '暂无评级'))
            model.item(rowNum, 14).setTextAlignment(Qt.AlignCenter)
            model.setItem(rowNum, 15, QStandardItem(jjpjList[3] if jjpjList[3] else '暂无评级'))
            model.item(rowNum, 15).setTextAlignment(Qt.AlignCenter)
            model.setItem(rowNum, 16, QStandardItem(jjpjList[4] if jjpjList[4] else '暂无评级'))
            model.item(rowNum, 16).setTextAlignment(Qt.AlignCenter)

            for idx in range(1, len(jjpjList)):
                if len(jjpjList[idx]) > 3:
                    model.item(rowNum, 12 + idx).setForeground(QBrush(QColor(220, 0, 0)))
        else:
            for idx in range(17):
                if idx == 0 or idx == 1:
                    model.setItem(rowNum, idx, QStandardItem(jdsyList[idx]))
                    model.item(rowNum, idx).setTextAlignment(Qt.AlignCenter)
                else:
                    model.setItem(rowNum, idx, QStandardItem('---'))
                    model.item(rowNum, idx).setTextAlignment(Qt.AlignCenter)
                model.item(rowNum, idx).setForeground(QBrush(QColor(186, 191, 195)))

    def clear(self):
        rowNum = self.model().rowCount()
        for _ in range(rowNum):
            self.model().removeRow(0)

    def showEvent(self, a0):
        if self.isSel:
            self.clear()

            th = Thread(target=self.dataThread)
            th.setDaemon(True)
            th.start()

        if a0:
            super(SelfSelectionTableView, self).showEvent(a0)

    def onSelfSelWaring(self):
        if not self.msgBox.isVisible():
            self.msgBox.setText('当前自选基金过多，目前仅支持显示 {} 自选。请删除多余自选！'.format(config.getMaxFundsCount()))
            self.msgBox.show()

    @CatchExceptions
    def dataThread(self):
        try:
            for idx, data in enumerate(fundSelfSelectionInfo()):
                if idx == config.getMaxFundsCount() or idx > config.getMaxFundsCount():
                    self.selfSelWaringSignal.emit()
                    self.fundTabDataSignal.emit(data, False)
                else:
                    self.fundTabDataSignal.emit(data, True)
        except:
            pass



